/******************************************************************************
 *                  Shanghai ChipON Micro-Electronic Co.,Ltd
 ******************************************************************************
 *  @File Name        : kf8a100fxx_lin.h
 *  @Author           : ChipON AE/FAE Group
 *  @Date             : 2023-12-19
 *  @HW Version       : KF8A100Fxx
 *  @Lib Version      : V2.0.1
 *  @Description      : This file provides the driver for the lin module
 ******************************************************************************
 *  Copyright (C) by Shanghai ChipON Micro-Electronic Co.,Ltd
 *  All rights reserved.
 *
 *  This software is copyright protected and proprietary to
 *  Shanghai ChipON Micro-Electronic Co.,Ltd.
 *****************************************************************************/
/******************************************************************************
 *  |Date        |Version  |Author       |Description
 ******************************************************************************
 *  |2023-12-23  |V2.0     |Wang Junxiong|New creat
 *****************************************************************************/

#ifndef KF8A100FXX_LIN_H
#define KF8A100FXX_LIN_H

#ifdef __cplusplus
extern "C" {
#endif

/******************************************************************************
 *                      Include Files
 *****************************************************************************/
#include "kf8a100fxx.h"
/******************************************************************************
 *                      Macro or Inline
 *****************************************************************************/

/**
 * @brief timeout: time limit for flag query, Must not be less than SystemClock/4/BaudRate*10/8
 * You can set it larger if time permits, SystemClock/4/BaudRate*10/8*1.5
 * 0 ~ 65535
 *
 */
#define LIN_TIMEOUT_CONFIG (uint16_t)3100u

/**
 * @brief lin module disable/enable
 * 0: disable, 1:enable
 *
 */
#define LIN1_ENABLE(x) (SPEN1 = (x))
#define LIN2_ENABLE(x) (SPEN2 = (x))
/******************************************************************************
 *                      Typedef Definitions
 *****************************************************************************/

typedef enum
{
    /** @brief General Inspection. */
    LIN_CHECKSUM_CLASSIC = 0u,
    /** @brief Enhanced screening.*/
    LIN_CHECKSUM_ENHANCEMENT = 1u
} Lin_CheckSumType;

/**
 * @brief LIN baud rate. Based on 16MHz
 */
typedef enum
{
    /** @brief theoretical error: 0.08% */
    LIN_BAUDRATE_2400 = 416u,
    /** @brief theoretical error: 0.16% */
    LIN_BAUDRATE_4800 = 207u,
    /** @brief theoretical error: 0.16% */
    LIN_BAUDRATE_9600 = 103u,
    /** @brief theoretical error: 0.64% */
    LIN_BAUDRATE_14400 = 68u,
    /** @brief theoretical error: 0.16% */
    LIN_BAUDRATE_19200 = 51u
} Lin_BaudRateModeType;

/**
 * @brief LIN timeout error type.
 */
typedef enum
{
    LIN_OK,
    LIN_TIMEOUT
} Lin_StatusType;

/**
 * @brief LIN receive status type.
 */
typedef enum
{
    LIN_RX_IDLE     = 0u,
    LIN_RX_START    = 1u,
    LIN_RX_PROGRESS = 2u,
    LIN_RX_COMPLETE = 3u
} Lin_RxStatusType;
/******************************************************************************
 *                      Export Variables
 *****************************************************************************/

/******************************************************************************
 *                      Export Functions
 *****************************************************************************/

/**
 * @brief LIN1 initialize
 *
 * @param Prescaler = the baud rate is 16000000/[16*(prescaler+1)]
 */
void Lin1_Init(Lin_BaudRateModeType Prescaler);

/**
 * @brief LIN1 initialize
 *
 * @param Prescaler = the baud rate is 16000000/[16*(prescaler+1)]
 */
void Lin2_Init(Lin_BaudRateModeType Prescaler);

/**
 * @brief The parity bit of temp is calculated as follows: ID6 is the odd check of ID0, ID1, ID2, and ID4, and ID7 is
 * the even check of ID1, ID3, ID4, and ID5. The result of the calculation is taken as the PID. The lin peripheral is
 * then driven to send a head signal for the Lin communication. Includes: 13-bit spacer characters, synchronous
 * characters, and PID.
 *
 * @param LinId The Lin ID number, only 0-5 digits is valid. 0x00u~0x3fu
 * @return Lin_StatusType
 * 0: LIN_OK,
 * 1: LIN_TIMEOUT,
 */
Lin_StatusType Lin1_SendHead(uint8_t LinId);

/**
 * @brief The parity bit of temp is calculated as follows: ID6 is the odd check of ID0, ID1, ID2, and ID4, and ID7 is
 * the even check of ID1, ID3, ID4, and ID5. The result of the calculation is taken as the PID. The lin peripheral is
 * then driven to send a head signal for the Lin communication. Includes: 13-bit spacer characters, synchronous
 * characters, and PID.
 *
 * @param LinId The Lin ID number, only 0-5 digits is valid. 0x00u~0x3fu
 * @return Lin_StatusType
 * 0: LIN_OK,
 * 1: LIN_TIMEOUT,
 */
Lin_StatusType Lin2_SendHead(uint8_t LinId);

/**
 * @brief Send the temp as data first. Then calculate the reverse code of temp, and then send the reverse code as a
 * check character
 *
 * @attention This function cannot be called within an interrupt service routine.
 *
 * @param LinId The slaver ID number, only 0-5 digits is valid. 0x00u~0x3fu
 * @param CheckSumType Type of inspection.
 * @param Buff Address for sending data
 * @param Len Length of sent data, 1u~8u
 * @return Lin_StatusType
 * 0: LIN_OK,
 * 1: LIN_TIMEOUT,
 */
Lin_StatusType Lin1_SendFrame(uint8_t LinId, Lin_CheckSumType CheckSumType, const uint8_t *Buff, uint8_t Len);

/**
 * @brief Send the temp as data first. Then calculate the reverse code of temp, and then send the reverse code as a
 * check character
 *
 * @attention This function cannot be called within an interrupt service routine.
 *
 * @param LinId The slaver ID number, only 0-5 digits is valid. 0x00u~0x3fu
 * @param CheckSumType Type of inspection.
 * @param Buff Address for sending data
 * @param Len Length of sent data, 1u~8u
 * @return Lin_StatusType
 * 0: LIN_OK,
 * 1: LIN_TIMEOUT,
 */
Lin_StatusType Lin2_SendFrame(uint8_t LinId, Lin_CheckSumType CheckSumType, const uint8_t *Buff, uint8_t Len);

/**
 * @brief Receive a byte
 *
 * @return uint8_t data, error returns 0
 */
uint8_t Lin1_Rec_Byte(void);

/**
 * @brief Receive a byte
 *
 * @return uint8_t data, error returns 0
 */
uint8_t Lin2_Rec_Byte(void);

/**
 * @brief Received data: contains 00 55 ID DATA[n] checksums
 *
 * @attention This function cannot be called within an interrupt service routine.
 *
 * @param Buff Address for data
 * @param Len Length of data, 2u~9u
 * @return Lin_StatusType
 * 0: LIN_OK,
 * 1: LIN_TIMEOUT,
 */
Lin_StatusType Lin1_RecvData(uint8_t *Buff, uint8_t Len);

/**
 * @brief Received data: contains 00 55 ID DATA[n] checksums
 *
 * @attention This function cannot be called within an interrupt service routine.
 *
 * @param Buff Address for data
 * @param Len Length of data, 2u~9u
 * @return Lin_StatusType
 * 0: LIN_OK,
 * 1: LIN_TIMEOUT,
 */
Lin_StatusType Lin2_RecvData(uint8_t *Buff, uint8_t Len);

/**
 * @brief Lin1 deinitialization
 *
 */
void Lin1_DeInit(void);

/**
 * @brief Lin2 deinitialization
 *
 */
void Lin2_DeInit(void);

/**
 * @brief: Get checksum value
 * LIN_CHECKSUM_CLASSIC: Lin_GetCheckSumValue(Buff[0], &Buff[1], Len - 1u);
 * LIN_CHECKSUM_ENHANCEMENT: Lin_GetCheckSumValue(PId, Buff, Len);
 *
 * @attention This function cannot be called within an interrupt service routine.
 *
 * @param PctID PID or Buff[0]
 * @param DataBuf Buff or &Buff[1]
 * @param Length Len or Len - 1
 * @retval uint8_t checksum value
 */
uint8_t Lin_GetCheckSumValue(uint8_t PctID, const uint8_t *DataBuf, uint8_t Length);

/**
 * @brief: Calculate PID
 *
 * @param LinId Lin ID 0x00~0x3f
 * @retval uint8_t PID
 */
uint8_t Lin_GetParityValue(uint8_t LinId);

#ifdef __cplusplus
}
#endif

#endif
/* EOF */
